﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Xml;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

namespace _2D
{
    public class Character : ICollisionable
    {
        // TODO: La clase Character debe de ser una clase abstracta de la que deriben los metodos para cada uno de los personajes del juego.

        public AnimationXML[] characterAnimation;           // Un personaje puede tener varias animaciones.
        public int currentAnimation;


        string xmlFile;
        int frameCount;
        int framesPerSec;
        int bbwidth;    // Ancho y alto del rectángulo de colisiones de la animación.
        int bbheight;        
        float scale;
        private Rectangle _boundingBox;
        Vector2 _position;
        Vector2 _beforePosition;
        XmlDocument animationXML;
        Keys[] currentKeys;
        Keys[] preseedKeys;     // Almacena las teclas pulsadas para cuando currentKeys vale 0.

        public Rectangle boundingBox
        {
            get
            {
                return _boundingBox;
            }
        }
        
        public Vector2 position
        {
            get
            {
                return _position;
            }
            set
            {
                _position = value;
            }
        }

        public Vector2 beforePosition
        {
            get
            {
                return _beforePosition;
            }
            set
            {
                _beforePosition = value;
            }
        }

        

        public Character(int x, int y, string paramXmlFileName, ContentManager content)
        {
            _position = new Vector2(x, y);
            xmlFile = paramXmlFileName;

            currentAnimation = 0;

            animationXML = new XmlDocument();
            animationXML.Load(paramXmlFileName);

            XmlNodeList animations = animationXML.GetElementsByTagName("Animation");

            characterAnimation = new AnimationXML[animations.Count];

            for (int i = 0; i < animations.Count; i++)
            {
               // /Animations/Animation[1]/configuration/FrameCount

                string file = ((XmlElement)animations[i]).GetElementsByTagName("File")[0].InnerText;
                frameCount = int.Parse(((XmlElement)animations[i]).GetElementsByTagName("FrameCount")[0].InnerText);
                framesPerSec = int.Parse(((XmlElement)animations[i]).GetElementsByTagName("FramesPerSec")[0].InnerText);
                bbwidth = int.Parse(((XmlElement)animations[i]).GetElementsByTagName("AnimationWidth")[0].InnerText);
                bbheight = int.Parse(((XmlElement)animations[i]).GetElementsByTagName("AnimationHeight")[0].InnerText);
                scale = float.Parse(((XmlElement)animations[i]).GetElementsByTagName("Scale")[0].InnerText);
                AnimationXML animationAux = new AnimationXML(new Vector2(0,0), frameCount, framesPerSec, bbwidth, bbheight);
                // animationAux.Load(content, ;
                animationAux.Load(content, file, ((XmlElement)animations[i]).GetElementsByTagName("Sprite"));
                characterAnimation[i] = animationAux;
            }


            // TODO: Revisar. Asumimos que las variables bbwidth y bbheight valen lo mismo para todas las animaciones.
            _boundingBox = new Rectangle((int)_position.X, (int)_position.Y, bbwidth, bbheight);
        }

        /// <summary>
        /// El movimiento se realiza en game. Aquí definimos la animación.
        /// </summary>
        /// <param name="ks"></param>
        /// <param name="gameTime"></param>
        /// <param name="moveCharacter"></param>
        public void Update(KeyboardState ks, GameTime gameTime)
        {
            //2 	(Abajo) 	    0
            //1 	(Abajo-izq) 	1
            //4	    (Izquierda)	    2
            //7	    (Arriba-izq)	3
            //8	    (Arriba)	    4
            //9	    (Arriba-der)	5
            //6	    (Derecha)	    6
            //3	    (Abajo-der)	    7

            _beforePosition = position;     // Almacenamos la última posición para volver en caso de colisión.
            currentKeys = new Keys[0];

            bool move = false;

            if (ks.IsKeyDown(Keys.Left))
            {
                //if (moveCharacter)
                    _position.X = _position.X - 1;
                currentAnimation = 2;
                move = true;

                addCurrentKey(Keys.Left);
            }

            if (ks.IsKeyDown(Keys.Right))
            {
                //if (moveCharacter) 
                    _position.X = _position.X + 1;
                currentAnimation = 6;
                move = true;

                addCurrentKey(Keys.Right);
            }

            if (ks.IsKeyDown(Keys.Up))
            {
                //if (moveCharacter) 
                    _position.Y = _position.Y - 1;
                currentAnimation = 4;
                move = true;

                addCurrentKey(Keys.Up);
            }

            if (ks.IsKeyDown(Keys.Down))
            {
                //if (moveCharacter) 
                    _position.Y = _position.Y + 1;
                currentAnimation = 0;
                move = true;

                addCurrentKey(Keys.Down);
            }


            if (move)
                characterAnimation[currentAnimation].Update((float)gameTime.ElapsedGameTime.TotalSeconds);

            
        }

        public void addCurrentKey(Keys key)
        {
            int newPositionInArray = currentKeys.Length + 1;
            Array.Resize(ref currentKeys, newPositionInArray);
            currentKeys[newPositionInArray - 1] = key;
        }

        public void Draw(SpriteBatch batch, Vector2 cameraPosition)
        {
            characterAnimation[currentAnimation].Draw(batch, position, scale, cameraPosition);

            _boundingBox.X = (int)position.X;
            _boundingBox.Y = (int)position.Y;
        }

        public void AtferCollisionAction()
        {
            //_position = _beforePosition;
            //_position = new Vector2(200,200);

            if (currentKeys.Length > 0)
            {
                preseedKeys = currentKeys;
            }

            foreach (Keys key in preseedKeys)
            {
                switch (key)
                {
                    case Keys.Up:
                        _position.Y = _position.Y + 2;
                        break;

                    case Keys.Down:
                        _position.Y = _position.Y - 2;
                        break;

                    case Keys.Left:
                        _position.X = _position.X + 2;
                        break;

                    case Keys.Right:
                        _position.X = _position.X - 2;
                        break;
                }
            }

            //characterAnimation[currentAnimation].Draw(batch, position, scale, cameraPosition);

            _boundingBox.X = (int)position.X;
            _boundingBox.Y = (int)position.Y;
        }

        public Rectangle GetBoundingBox()
        {
            return _boundingBox;
        }
    }
}
